package icraf.carbon.gui.chart;

import static java.awt.font.TextAttribute.FAMILY;
import static java.awt.font.TextAttribute.POSTURE;
import static java.awt.font.TextAttribute.POSTURE_OBLIQUE;
import static java.awt.font.TextAttribute.SIZE;
import static java.awt.font.TextAttribute.STRIKETHROUGH;
import static java.awt.font.TextAttribute.STRIKETHROUGH_ON;
import static java.awt.font.TextAttribute.SUPERSCRIPT;
import static java.awt.font.TextAttribute.SUPERSCRIPT_SUB;
import static java.awt.font.TextAttribute.SUPERSCRIPT_SUPER;
import static java.awt.font.TextAttribute.UNDERLINE;
import static java.awt.font.TextAttribute.UNDERLINE_LOW_ONE_PIXEL;
import static java.awt.font.TextAttribute.WEIGHT;
import static java.awt.font.TextAttribute.WEIGHT_BOLD;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GraphicsEnvironment;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.font.TextAttribute;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListCellRenderer;
import javax.swing.ListModel;
import javax.swing.border.CompoundBorder;
import javax.swing.border.LineBorder;
import javax.swing.border.MatteBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;

public class FontChooser extends JPanel {
	private static final long serialVersionUID = -3379491062178516621L;

	// protected int Closed_Option = JOptionPane.CLOSED_OPTION;

	protected InputList fontNameInputList = new InputList(fontNames, "Name:");

	protected InputList fontSizeInputList = new InputList(fontSizes, "Size:");

	protected MutableAttributeSet attributes;

	protected JCheckBox boldCheckBox = new JCheckBox("Bold");

	protected JCheckBox italicCheckBox = new JCheckBox("Italic");

	protected JCheckBox underlineCheckBox = new JCheckBox("Underline");

	protected JCheckBox strikethroughCheckBox = new JCheckBox("Strikethrough");

	protected JCheckBox subscriptCheckBox = new JCheckBox("Subscript");

	protected JCheckBox superscriptCheckBox = new JCheckBox("Superscript");

	//protected ColorComboBox colorComboBox;

	protected FontLabel previewLabel;

	public static String[] fontNames;

	public static String[] fontSizes;

	private static final String PREVIEW_TEXT = "Preview Font";
	private JButton colorButton;
	private ColorIcon colorIcon;
	private Color color = Color.black;
	
	public FontChooser() {
		GraphicsEnvironment ge = GraphicsEnvironment
				.getLocalGraphicsEnvironment();
		fontNames = ge.getAvailableFontFamilyNames();
		fontSizes = new String[] { "8", "9", "10", "11", "12", "14", "16",
				"18", "20", "22", "24", "26", "28", "36", "48", "72" };
		fontNameInputList = new InputList(fontNames, "Name:");

		fontSizeInputList = new InputList(fontSizes, "Size:");

		setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));

		//JPanel p = new JPanel(new GridLayout(1, 2, 10, 2));
		JPanel p = new JPanel(new BorderLayout(5,5));
		p.setBorder(new TitledBorder(BorderFactory
				.createLineBorder(Color.lightGray), "Font"));
		p.add(fontNameInputList);
		fontNameInputList.setDisplayedMnemonic('n');
		fontNameInputList.setToolTipText("Font name");

		//p.add(fontSizeInputList);
		//fontSizeInputList.g
		p.add(fontSizeInputList, BorderLayout.EAST);
		fontSizeInputList.setDisplayedMnemonic('s');
		fontSizeInputList.setToolTipText("Font size");
		fontSizeInputList.setFieldColumn(6);
		add(p);

		p = new JPanel(new GridLayout(3, 2, 0, 0));
		p.setBorder(new TitledBorder(BorderFactory
				.createLineBorder(Color.lightGray), "Effects"));
		boldCheckBox.setMnemonic('b');
		boldCheckBox.setToolTipText("Bold font");
		p.add(boldCheckBox);

		italicCheckBox.setMnemonic('i');
		italicCheckBox.setToolTipText("Italic font");
		p.add(italicCheckBox);

		underlineCheckBox.setMnemonic('u');
		underlineCheckBox.setToolTipText("Underline font");
		p.add(underlineCheckBox);

		strikethroughCheckBox.setMnemonic('r');
		strikethroughCheckBox.setToolTipText("Strikethrough font");
		p.add(strikethroughCheckBox);

		subscriptCheckBox.setMnemonic('t');
		subscriptCheckBox.setToolTipText("Subscript font");
		p.add(subscriptCheckBox);

		superscriptCheckBox.setMnemonic('p');
		superscriptCheckBox.setToolTipText("Superscript font");
		p.add(superscriptCheckBox);
		
		//add(p);

		colorButton = new JButton();
		colorButton.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				Color c = JColorChooser.showDialog(colorButton, "Font Color", color);
				if(c != null) {
//					color = c;
//					colorIcon.color = c;
//					colorButton.repaint();
//					updatePreview();
					setSettingColor(c);
				}
				
			}
		});
		colorIcon = new ColorIcon(color, 50, 40);
		colorButton.setIcon(colorIcon);
		colorButton.setPreferredSize(new Dimension( 45, 45));
		JPanel pb = new JPanel(new BorderLayout());
		pb.setBorder(new TitledBorder(BorderFactory
				.createLineBorder(Color.lightGray), "Color"));
		pb.add(colorButton);
		
		JPanel pStyle = new JPanel();
		pStyle.setLayout(new BoxLayout(pStyle, BoxLayout.X_AXIS));
		p.setPreferredSize(new Dimension(250,80));
		pStyle.add(p);
		pStyle.add(pb);
		add(pStyle);
		
		p = new JPanel(new BorderLayout());
		p.setBorder(new TitledBorder(BorderFactory
				.createCompoundBorder(BorderFactory
						.createLineBorder(Color.lightGray), BorderFactory
						.createEmptyBorder(0, 5, 5, 5)), "Preview"));
		previewLabel = new FontLabel(PREVIEW_TEXT);
		previewLabel.setPreferredSize(new Dimension(400, 150));
		p.add(previewLabel, BorderLayout.CENTER);
		add(p);

		// p = new JPanel(new FlowLayout());
		// JPanel p1 = new JPanel(new GridLayout(1, 2, 10, 2));
		// JButton btOK = new JButton("OK");
		// btOK.setToolTipText("Save and exit");
		// getRootPane().setDefaultButton(btOK);
		// ActionListener actionListener = new ActionListener() {
		// public void actionPerformed(ActionEvent e) {
		// Closed_Option = JOptionPane.OK_OPTION;
		// dispose();
		// }
		// };
		// btOK.addActionListener(actionListener);
		// p1.add(btOK);

		// JButton btCancel = new JButton("Cancel");
		// btCancel.setToolTipText("Exit without save");
		// actionListener = new ActionListener() {
		// public void actionPerformed(ActionEvent e) {
		// Closed_Option = JOptionPane.CANCEL_OPTION;
		// dispose();
		// }
		// };
		// btCancel.addActionListener(actionListener);
		// p1.add(btCancel);
		// p.add(p1);
		// add(p);

		ListSelectionListener listSelectListener = new ListSelectionListener() {
			public void valueChanged(ListSelectionEvent e) {
				updatePreview();
			}
		};
		fontNameInputList.addListSelectionListener(listSelectListener);
		fontSizeInputList.addListSelectionListener(listSelectListener);

		ActionListener actionListener = new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				updatePreview();
			}
		};
		boldCheckBox.addActionListener(actionListener);
		italicCheckBox.addActionListener(actionListener);
		//colorComboBox.addActionListener(actionListener);
		underlineCheckBox.addActionListener(actionListener);
		strikethroughCheckBox.addActionListener(actionListener);
		subscriptCheckBox.addActionListener(actionListener);
		superscriptCheckBox.addActionListener(actionListener);
	}

//	private void setAttributes(AttributeSet a) {
//		attributes = new SimpleAttributeSet(a);
//		String name = StyleConstants.getFontFamily(a);
//		fontNameInputList.setSelected(name);
//		int size = StyleConstants.getFontSize(a);
//		fontSizeInputList.setSelectedInt(size);
//		boldCheckBox.setSelected(StyleConstants.isBold(a));
//		italicCheckBox.setSelected(StyleConstants.isItalic(a));
//		underlineCheckBox.setSelected(StyleConstants.isUnderline(a));
//		strikethroughCheckBox.setSelected(StyleConstants.isStrikeThrough(a));
//		subscriptCheckBox.setSelected(StyleConstants.isSubscript(a));
//		superscriptCheckBox.setSelected(StyleConstants.isSuperscript(a));
//		updatePreview();
//	}

//	public AttributeSet getAttributes() {
//		if (attributes == null)
//			return null;
//		StyleConstants.setFontFamily(attributes, fontNameInputList
//				.getSelected());
//		StyleConstants.setFontSize(attributes, fontSizeInputList
//				.getSelectedInt());
//		StyleConstants.setBold(attributes, boldCheckBox.isSelected());
//		StyleConstants.setItalic(attributes, italicCheckBox.isSelected());
//		StyleConstants.setUnderline(attributes, underlineCheckBox.isSelected());
//		StyleConstants.setStrikeThrough(attributes, strikethroughCheckBox
//				.isSelected());
//		StyleConstants.setSubscript(attributes, subscriptCheckBox.isSelected());
//		StyleConstants.setSuperscript(attributes, superscriptCheckBox
//				.isSelected());
//		StyleConstants.setForeground(attributes, color);
//		return attributes;
//	}

	// public int getOption() {
	// return Closed_Option;
	// }

	protected void updatePreview() {
		StringBuilder previewText = new StringBuilder(PREVIEW_TEXT);
		String name = fontNameInputList.getSelected();
		int size = fontSizeInputList.getSelectedInt();
		if (size <= 0)
			return;

		Map<TextAttribute, Object> attributes = new HashMap<TextAttribute, Object>();

		attributes.put(FAMILY, name);
		attributes.put(SIZE, (float) size);

		// Using HTML to force JLabel manage natively unsupported attributes
		if (underlineCheckBox.isSelected()
				|| strikethroughCheckBox.isSelected()) {
			previewText.insert(0, "<html>");
			previewText.append("</html>");
		}

		if (underlineCheckBox.isSelected()) {
			attributes.put(UNDERLINE, UNDERLINE_LOW_ONE_PIXEL);
			previewText.insert(6, "<u>");
			previewText.insert(previewText.length() - 7, "</u>");
		}
		if (strikethroughCheckBox.isSelected()) {
			attributes.put(STRIKETHROUGH, STRIKETHROUGH_ON);
			previewText.insert(6, "<strike>");
			previewText.insert(previewText.length() - 7, "</strike>");
		}

		if (boldCheckBox.isSelected())
			attributes.put(WEIGHT, WEIGHT_BOLD);
		if (italicCheckBox.isSelected())
			attributes.put(POSTURE, POSTURE_OBLIQUE);

		if (subscriptCheckBox.isSelected()) {
			attributes.put(SUPERSCRIPT, SUPERSCRIPT_SUB);
		}
		if (superscriptCheckBox.isSelected())
			attributes.put(SUPERSCRIPT, SUPERSCRIPT_SUPER);

		superscriptCheckBox.setEnabled(!subscriptCheckBox.isSelected());
		subscriptCheckBox.setEnabled(!superscriptCheckBox.isSelected());

		Font fn = new Font(attributes);

		previewLabel.setText(previewText.toString());
		previewLabel.setFont(fn);

		//Color c = (Color) colorComboBox.getSelectedItem();
		previewLabel.setForeground(color);
		//previewLabel.setForeground(c);
		previewLabel.repaint();
	}
	
	public Font getSettingFont() {
		String name = fontNameInputList.getSelected();
		int size = fontSizeInputList.getSelectedInt();
	
		Map<TextAttribute, Object> attributes = new HashMap<TextAttribute, Object>();

		attributes.put(FAMILY, name);
		attributes.put(SIZE, (float) size);


		if (underlineCheckBox.isSelected()) 
			attributes.put(UNDERLINE, UNDERLINE_LOW_ONE_PIXEL);
		if (strikethroughCheckBox.isSelected()) 
			attributes.put(STRIKETHROUGH, STRIKETHROUGH_ON);
		if (boldCheckBox.isSelected())
			attributes.put(WEIGHT, WEIGHT_BOLD);
		if (italicCheckBox.isSelected())
			attributes.put(POSTURE, POSTURE_OBLIQUE);
		if (subscriptCheckBox.isSelected()) 
			attributes.put(SUPERSCRIPT, SUPERSCRIPT_SUB);
		if (superscriptCheckBox.isSelected())
			attributes.put(SUPERSCRIPT, SUPERSCRIPT_SUPER);

		superscriptCheckBox.setEnabled(!subscriptCheckBox.isSelected());
		subscriptCheckBox.setEnabled(!superscriptCheckBox.isSelected());
		
		return new Font(attributes);
	}
	
	public void setSettingFont(Font f) {
		if(f == null) return;
		fontNameInputList.setSelected(f.getFamily());
		fontSizeInputList.setSelectedInt(f.getSize());
		boldCheckBox.setSelected(f.isBold());
		italicCheckBox.setSelected(f.isItalic());
		underlineCheckBox.setSelected(f.getAttributes().get(UNDERLINE)==UNDERLINE_LOW_ONE_PIXEL);
		strikethroughCheckBox.setSelected(f.getAttributes().get(STRIKETHROUGH)==STRIKETHROUGH_ON);
		subscriptCheckBox.setSelected(f.getAttributes().get(SUPERSCRIPT)==SUPERSCRIPT_SUB);
		superscriptCheckBox.setSelected(f.getAttributes().get(SUPERSCRIPT)==SUPERSCRIPT_SUPER);
		updatePreview();
	}
	
	public FontFormat getFontFormat() {
		FontFormat ff = new FontFormat();
		ff.font = getSettingFont();
		ff.fontColor = getSettingColor();
//		ff.attributeSet = getAttributes();
		return ff;
	}
	
	public void setFontFormat(FontFormat ff) {
		setSettingFont(ff.font);
		setSettingColor(ff.fontColor);
		//setAttributes(ff.attributeSet);
	}
	
	public static void main(String argv[]) {
		GraphicsEnvironment ge = GraphicsEnvironment
				.getLocalGraphicsEnvironment();
		fontNames = ge.getAvailableFontFamilyNames();
		fontSizes = new String[] { "8", "9", "10", "11", "12", "14", "16",
				"18", "20", "22", "24", "26", "28", "36", "48", "72" };

		FontChooser dlg = new FontChooser();
		SimpleAttributeSet a = new SimpleAttributeSet();
		StyleConstants.setFontFamily(a, "Monospaced");
		StyleConstants.setFontSize(a, 12);
		//dlg.setAttributes(a);
		dlg.setVisible(true);
	}

	public Color getSettingColor() {
		return color;
	}
	
	public void setSettingColor(Color c) {
		color = c;
		previewLabel.setForeground(color);
		colorIcon.color = c;
		colorButton.repaint();
	}
}

class InputList extends JPanel implements ListSelectionListener, ActionListener {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1526928816560606527L;

	protected JLabel label = new JLabel();

	protected JTextField textfield;

	protected JList list;

	protected JScrollPane scroll;

	public InputList(String[] data, String title) {
		setLayout(null);

		add(label);
		textfield = new OpelListText();
		textfield.addActionListener(this);
		label.setLabelFor(textfield);
		add(textfield);
		list = new OpelListList(data);
		list.setVisibleRowCount(4);
		list.addListSelectionListener(this);
		scroll = new JScrollPane(list);
		scroll.setBorder(BorderFactory.createEmptyBorder(5, 2, 2, 0));
		add(scroll);
	}

	public InputList(String title, int numCols) {
		setLayout(null);
		label = new OpelListLabel(title, JLabel.LEFT);
		add(label);
		textfield = new OpelListText(numCols);
		textfield.addActionListener(this);
		label.setLabelFor(textfield);
		add(textfield);
		list = new OpelListList();
		list.setVisibleRowCount(4);
		list.addListSelectionListener(this);
		scroll = new JScrollPane(list);
		add(scroll);
	}

	public void setFieldColumn(int c) {
		textfield.setColumns(c);
	}
	public void setToolTipText(String text) {
		super.setToolTipText(text);
		label.setToolTipText(text);
		textfield.setToolTipText(text);
		list.setToolTipText(text);
	}

	public void setDisplayedMnemonic(char ch) {
		label.setDisplayedMnemonic(ch);
	}

	public void setSelected(String sel) {
		list.setSelectedValue(sel, true);
		textfield.setText(sel);
	}

	public String getSelected() {
		return textfield.getText();
	}

	public void setSelectedInt(int value) {
		setSelected(Integer.toString(value));
	}

	public int getSelectedInt() {
		try {
			return Integer.parseInt(getSelected());
		} catch (NumberFormatException ex) {
			return -1;
		}
	}

	public void valueChanged(ListSelectionEvent e) {
		Object obj = list.getSelectedValue();
		if (obj != null)
			textfield.setText(obj.toString());
	}

	public void actionPerformed(ActionEvent e) {
		ListModel model = list.getModel();
		String key = textfield.getText().toLowerCase();
		for (int k = 0; k < model.getSize(); k++) {
			String data = (String) model.getElementAt(k);
			if (data.toLowerCase().startsWith(key)) {
				list.setSelectedValue(data, true);
				break;
			}
		}
	}

	public void addListSelectionListener(ListSelectionListener lst) {
		list.addListSelectionListener(lst);
	}

	public Dimension getPreferredSize() {
		Insets ins = getInsets();
		Dimension labelSize = label.getPreferredSize();
		Dimension textfieldSize = textfield.getPreferredSize();
		Dimension scrollPaneSize = scroll.getPreferredSize();
		int w = Math.max(Math.max(labelSize.width, textfieldSize.width),
				scrollPaneSize.width);
		int h = labelSize.height + textfieldSize.height + scrollPaneSize.height;
		return new Dimension(w + ins.left + ins.right, h + ins.top + ins.bottom);
	}

	public Dimension getMaximumSize() {
		return getPreferredSize();
	}

	public Dimension getMinimumSize() {
		return getPreferredSize();
	}

	public void doLayout() {
		Insets ins = getInsets();
		Dimension size = getSize();
		int x = ins.left;
		int y = ins.top;
		int w = size.width - ins.left - ins.right;
		int h = size.height - ins.top - ins.bottom;

		Dimension labelSize = label.getPreferredSize();
		label.setBounds(x, y, w, labelSize.height);
		y += labelSize.height;
		Dimension textfieldSize = textfield.getPreferredSize();
		textfield.setBounds(x, y, w, textfieldSize.height);
		y += textfieldSize.height;
		scroll.setBounds(x, y, w, h - y);
	}

	public void appendResultSet(ResultSet results, int index,
			boolean toTitleCase) {
		textfield.setText("");
		DefaultListModel model = new DefaultListModel();
		try {
			while (results.next()) {
				String str = results.getString(index);
				if (toTitleCase) {
					str = Character.toUpperCase(str.charAt(0))
							+ str.substring(1);
				}

				model.addElement(str);
			}
		} catch (SQLException ex) {
			System.err.println("appendResultSet: " + ex.toString());
		}
		list.setModel(model);
		if (model.getSize() > 0)
			list.setSelectedIndex(0);
	}

	class OpelListLabel extends JLabel {
		/**
	 * 
	 */
		private static final long serialVersionUID = 3153981804742447244L;

		public OpelListLabel(String text, int alignment) {
			super(text, alignment);
		}

		public AccessibleContext getAccessibleContext() {
			return InputList.this.getAccessibleContext();
		}
	}

	class OpelListText extends JTextField {
		/**
	 * 
	 */
		private static final long serialVersionUID = -5652396378253280056L;

		public OpelListText() {
		}

		public OpelListText(int numCols) {
			super(numCols);
		}

		public AccessibleContext getAccessibleContext() {
			return InputList.this.getAccessibleContext();
		}
	}

	class OpelListList extends JList {
		/**
	 * 
	 */
		private static final long serialVersionUID = 2076006675669067876L;

		public OpelListList() {
		}

		public OpelListList(String[] data) {
			super(data);
		}

		public AccessibleContext getAccessibleContext() {
			return InputList.this.getAccessibleContext();
		}
	}

	// Accessibility Support

	public AccessibleContext getAccessibleContext() {
		if (accessibleContext == null)
			accessibleContext = new AccessibleOpenList();
		return accessibleContext;
	}

	protected class AccessibleOpenList extends AccessibleJComponent {

		/**
	 * 
	 */
		private static final long serialVersionUID = 1089265284866057675L;

		public String getAccessibleName() {
			System.out.println("getAccessibleName: " + accessibleName);
			if (accessibleName != null)
				return accessibleName;
			return label.getText();
		}

		public AccessibleRole getAccessibleRole() {
			return AccessibleRole.LIST;
		}
	}
}

class FontLabel extends JLabel {
	/**
	 * 
	 */
	private static final long serialVersionUID = 833193094710908712L;

	public FontLabel(String text) {
		super(text, JLabel.CENTER);
		setBackground(Color.white);
		setForeground(Color.black);
		setOpaque(true);
		//setBorder(new LineBorder(Color.black));
		setPreferredSize(new Dimension(120, 40));
	}
}

class ColorComboBox extends JComboBox {

	/**
	 * 
	 */
	private static final long serialVersionUID = 8301245792540090167L;

	public ColorComboBox() {
		int[] values = new int[] { 0, 128, 192, 255 };
		for (int r = 0; r < values.length; r++)
			for (int g = 0; g < values.length; g++)
				for (int b = 0; b < values.length; b++) {
					Color c = new Color(values[r], values[g], values[b]);
					addItem(c);
				}
		setRenderer(new ColorComboRenderer1());

	}

	class ColorComboRenderer1 extends JPanel implements ListCellRenderer {
		/**
	 * 
	 */
		private static final long serialVersionUID = 3093291095262219407L;
		protected Color m_c = Color.black;

		public ColorComboRenderer1() {
			super();
			setBorder(new CompoundBorder(new MatteBorder(2, 10, 2, 10,
					Color.white), new LineBorder(Color.black)));
		}

		public Component getListCellRendererComponent(JList list, Object obj,
				int row, boolean sel, boolean hasFocus) {
			if (obj instanceof Color)
				m_c = (Color) obj;
			return this;
		}

		public void paint(Graphics g) {
			setBackground(m_c);
			super.paint(g);
		}

	}

}
